package com.whh.starter.cipher;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.SmUtil;

import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import cn.hutool.crypto.symmetric.SM4;
import com.whh.starter.properties.CipherProperties;

import java.security.KeyPair;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class SmServiceImpl implements CipherService {

    private final CipherProperties properties;

    public SmServiceImpl(CipherProperties properties) {
        this.properties = properties;
    }

    protected static Map<String, String> generateKeys() {
        Map<String, String> map = new HashMap<>();
        KeyPair sm2 = SecureUtil.generateKeyPair("SM2");
        String privateKey = Base64.getEncoder().encodeToString(sm2.getPrivate().getEncoded());
        String publicKey = Base64.getEncoder().encodeToString(sm2.getPublic().getEncoded());
        String secretKey = Base64.getEncoder().encodeToString(SecureUtil.generateKey(SM4.ALGORITHM_NAME, 128).getEncoded());
        map.put("privateKey", privateKey);
        map.put("publicKey", publicKey);
        map.put("secretKey", secretKey);
        System.out.println("map = " + map);

        return map;
    }

    public static String sm2Encrypt(String data, String publicKey, CipherProperties.KeyType keyType) {
        SM2 sm2 = SmUtil.sm2(null, publicKey);
        if (keyType.equals(CipherProperties.KeyType.BASE64)) {
            return sm2.encryptBase64(data, CharsetUtil.CHARSET_UTF_8, KeyType.PublicKey);
        }
        return sm2.encryptHex(data, CharsetUtil.CHARSET_UTF_8, KeyType.PublicKey);
    }

    public static String sm2Encrypt(String data, String publicKey) {
        return sm2Encrypt(data, publicKey, CipherProperties.KeyType.BASE64);
    }

    public static String sm2Decrypt(String data, String privateKey) {
        SM2 sm2 = SmUtil.sm2(privateKey, null);
        return sm2.decryptStr(data, KeyType.PrivateKey);
    }

    public static String SM4Encrypt(String data, String sm4Key, CipherProperties.KeyType keyType) {
//        SM4 sm4 = new SM4(Mode.ECB, Padding.PKCS5Padding,Base64.getDecoder().decode(sm4Key));
        //默认ecb/PKCS5Padding
        SM4 sm4 = new SM4(SecureUtil.decode(sm4Key));
        if (keyType.equals(CipherProperties.KeyType.BASE64)) {
            return sm4.encryptBase64(data);
        }
        return sm4.encryptHex(data);
    }

    public static String SM4Encrypt(String data, String sm4Key) {
        return SM4Encrypt(data, sm4Key, CipherProperties.KeyType.BASE64);
    }

    public static String SM4Decrypt(String data, String sm4Key) {
        SM4 sm4 = new SM4(Mode.ECB, Padding.PKCS5Padding, SecureUtil.decode(sm4Key));
        return sm4.decryptStr(data);
    }

    @Override
    public String symmetricEncrypt(String data, String secretKey) {
        return SM4Encrypt(data, secretKey, properties.getKeyType());
    }

    @Override
    public String symmetricDecrypt(String data, String secretKey) {
        //默认ecb/PKCS5Padding
        return SM4Decrypt(data, secretKey);
    }

    @Override
    public String asymmetricEncrypt(String data, String publicKey) {
        return sm2Encrypt(data, publicKey, properties.getKeyType());
    }

    @Override
    public String asymmetricDecrypt(String data) {
        return sm2Decrypt(data, properties.getPrivateKey());
    }
}
